#ifndef _REGISTER_HPP_
#define _REGISTER_HPP_
#include<string>
#include<vector>
#include<array>
using namespace std;
#define     BIT_8       0
#define     BIT_16      1
#define     BIT_32      2

enum class RegisterKind{
    UNKNOWN = -1,
    EAX_AX_AL,
    EBX_BX_BL,
    ECX_CX_CL,
    EDX_DX_DL
};

struct Register {
    static array<bool,4> reg_flags;
    static array<array<string,4>,3> reg_str;
    static array<Register*,4> status;
    RegisterKind reg_ind;

    Register():reg_ind(RegisterKind::UNKNOWN){}
    ~Register(){
        freeRegister();
    }
    RegisterKind getRegisterKind(){
        return reg_ind;
    }
    void moveRegister(Register& reg){
        if (this->reg_ind != RegisterKind::UNKNOWN)
            freeRegister();
        this->reg_ind = reg.reg_ind;
        status[(int)this->reg_ind] = this;
        reg.reg_ind = RegisterKind::UNKNOWN;
    }
    void swapRegister(RegisterKind registerKind){
        Register* temp = status[(int)registerKind];
        if (temp == nullptr){
            reg_flags[(int)reg_ind] = false;
            reg_flags[(int)registerKind] = true;
            reg_ind = registerKind;
        }
        else{
            swap(status[(int)this->reg_ind],status[(int)temp->reg_ind]);
            swap(this->reg_ind,temp->reg_ind);
        }
    }

    void swapRegister(Register* reg){
        swap(reg_flags[(int)this->reg_ind],reg_flags[(int)reg->reg_ind]);
        swap(this->reg_ind,reg->reg_ind);
    }

    static Register* getRegister(RegisterKind registerKind){
        return status[(int)registerKind];
    }

    void allocateRegister(){
        if (reg_ind != RegisterKind::UNKNOWN)
            return;

        for (int i = 0;i < sizeof(reg_flags) ;i++){
            if (reg_flags[(int)i] == false){
                reg_flags[(int)i] = true;
                status[(int)i] = this;
                reg_ind = (RegisterKind)i;
                usleep(100000);
                printf("正在为变量/常量/临时值申请寄存器%s...\n",getRegister32(reg_ind).data());
                return;
            }
        }
        usleep(100000);
        printf("错误：申请寄存器失败！！！！！！！！！！！！！！！！！！\n");
    }

    void freeRegister(){
        if (reg_ind == RegisterKind::UNKNOWN){
            return;
        }
        usleep(100000);
        printf("正在释放寄存器%s...\n",getRegister32(reg_ind).data());
        reg_flags[(int)reg_ind] = false;
        status[(int)reg_ind] = nullptr;
        reg_ind = RegisterKind::UNKNOWN;
    }
    string getRegister8() const {
        if (reg_ind == RegisterKind::UNKNOWN){
            usleep(100000);
            printf("错误：试图获取未分配寄存器的数据！！！！！！！！！！！\n");
        }
        
        return reg_str[BIT_8][(int)reg_ind];
    }
    string getRegister16()const {
        if (reg_ind == RegisterKind::UNKNOWN){
            usleep(100000);
            printf("错误：试图获取未分配寄存器的数据！！！！！！！！！！！\n");
        }
        
        return reg_str[BIT_16][(int)reg_ind];
    }

    string getRegister32() const {
        if (reg_ind == RegisterKind::UNKNOWN){
            usleep(100000);
            printf("错误：试图获取未分配寄存器的数据！！！！！！！！！！！\n");
        }
        
        return reg_str[BIT_32][(int)reg_ind];
    }

    static string getRegister32(RegisterKind registerKind) {
        if (registerKind == RegisterKind::UNKNOWN){
            usleep(100000);
            printf("错误：试图获取未分配寄存器的数据！！！！！！！！！！！\n");
            return "null register";
        }
        
        return reg_str[BIT_32][(int)registerKind];
    }
};
inline array<bool,4> Register::reg_flags = {false,false,false,false};
inline array<array<string,4>,3> Register::reg_str = {
    "al",  "bl",   "cl",   "dl",
    "ax",  "bx",   "cx",   "dx",
    "eax", "ebx",  "ecx",  "edx"};
inline array<Register*,4> Register::status = {nullptr,nullptr,nullptr,nullptr};

#endif